package com.heima.wemedia.service.impl;

import com.alibaba.fastjson.JSON;
import com.heima.common.aliyun.GreenImageScan;
import com.heima.common.aliyun.GreenTextScan;
import com.heima.common.tess4j.Tess4jClient;
import com.heima.feign.client.ArticleClient;
import com.heima.file.service.FileStorageService;
import com.heima.model.article.dtos.ArticleDto;
import com.heima.model.common.dtos.ResponseResult;
import com.heima.model.wemedia.pojos.WmSensitive;
import com.heima.model.wemedia.pojos.WmUser;
import com.heima.model.wmchannel.pojos.WmChannel;
import com.heima.model.wmnews.pojos.WmNews;
import com.heima.utils.common.SensitiveWordUtil;
import com.heima.wemedia.mapper.WmChannelMapper;
import com.heima.wemedia.mapper.WmNewsMapper;
import com.heima.wemedia.mapper.WmSensitiveMapper;
import com.heima.wemedia.mapper.WmUserMapper;
import com.heima.wemedia.service.WmNewsAutoScanService;
import lombok.extern.slf4j.Slf4j;
import net.sourceforge.tess4j.TesseractException;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.util.*;
import java.util.stream.Collectors;

@Service
@Slf4j
@Transactional
public class WmNewsAutoScanServiceImpl implements WmNewsAutoScanService {
    @Autowired
    private WmNewsMapper wmNewsMapper;
    @Autowired
    private GreenTextScan greenTextScan; // 检验文本
    @Autowired
    private GreenImageScan greenImageScan; // 检查图片信息
    @Autowired
    private FileStorageService fileStorageService; // 获取minio服务
    @Autowired
    private ArticleClient articleClient;
    @Autowired
    private WmChannelMapper wmChannelMapper;
    @Autowired
    private WmUserMapper wmUserMapper;
    @Autowired
    private WmSensitiveMapper wmSensitiveMapper;
    @Autowired
    private Tess4jClient tess4jClient;

    /**
     * 自媒体文章审核
     * @param newsId 自媒体文章id
     */
    @Override
    @Async
    public void autoScanWmNews(Integer newsId) {
        WmNews wmNews = wmNewsMapper.selectById(newsId);
        if (wmNews == null){
            return;
        }
        // 1,检验图片和文字
        Map<String, Object> map = drowOut(wmNews);
        // 自定义敏感词
        boolean sensitiveBool = sensitiveScan(wmNews, (String) map.get("content"));
        if(!sensitiveBool){
            return;
        }
        // 调用阿里接口检验文本
        boolean contentBool = textCheck(wmNews, (String) map.get("content"));
        if(!contentBool){
            return;
        }
        // 审核图片信息
        boolean imgBool = imgCheck(wmNews, (List) map.get("imglist"));
        if(!imgBool){
            return;
        }
        //远程调用Feign接口实现保存文章信息
        ResponseResult result = feignSaveNews(wmNews);
        if(result.getCode()!=200){
            return;
        }
        //5.修改wm_news表的状态
        wmNews.setArticleId((Long) result.getData());
        updateNewsStatus(wmNews, (short) 9,"发布成功");
    }

    /**
     * 自定义敏感词过滤
     * @param wmNews
     * @param content
     * @return
     */
    private boolean sensitiveScan(WmNews wmNews, String content){
        boolean flag = true;
        List<WmSensitive> wmSensitives = wmSensitiveMapper.selectList(null);
        List<String> collect = wmSensitives.stream()
                .map(WmSensitive::getSensitives)
                .collect(Collectors.toList()); // 获取自定义过滤词
        SensitiveWordUtil.initMap(collect);
        // 查看文章中是否包含敏感词汇
        Map<String, Integer> matchWords = SensitiveWordUtil.matchWords(content);
        if(matchWords.size()>0){
            updateNewsStatus(wmNews,(short) 2,"当前文章中存在违规内容"+matchWords);
            flag = false;
        }
        return flag;
    }

    /**
     * 调用feign保存文章信息
     * @param wmNews
     * @return
     */
    private ResponseResult feignSaveNews(WmNews wmNews){
        // 因为接收数据是ArticleDto,所以需要拷贝到Dto对象中
        ArticleDto articleDto = new ArticleDto();
        BeanUtils.copyProperties(wmNews, articleDto);
        articleDto.setLayout(wmNews.getType()); //文章布局
        //获取频道名称
        WmChannel channel = wmChannelMapper.selectById(wmNews.getChannelId());
        if(channel != null){
            articleDto.setChannelName(channel.getName());
        }
        // 作者
        long userId = wmNews.getUserId().longValue();
        articleDto.setAuthorId(userId);
        // 查询作者姓名
        WmUser wmUser = wmUserMapper.selectById(userId);
        if(wmUser != null){
            articleDto.setAuthorName(wmUser.getName());
        }
        if(wmNews.getArticleId() != null){
            articleDto.setId(wmNews.getArticleId());
        }
        articleDto.setCreatedTime(new Date());
        ResponseResult responseResult = articleClient.saveAparticle(articleDto);
        return responseResult;
    }

    /**
     * 检查图片信息,封面和内容
     * @param wmNews
     * @param imgList
     * @return
     */

    public boolean imgCheck(WmNews wmNews, List<String> imgList){
        boolean flag = true;
        List<byte[]> imageByteList=new ArrayList<>(); //存放二进制文件
        if(imgList!=null && imgList.size()>0){
            imgList = imgList.stream().distinct().collect(Collectors.toList());
            // 需要下载下来才能够调取阿jdk检查图片信息
            try {
                for (String img : imgList) {
                    byte[] bytes = fileStorageService.downLoadFile(img);
                    // 调用OCR图片文字识别,查看是否存在违法信息
                    ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(bytes);
                    BufferedImage bufferedImage = ImageIO.read(byteArrayInputStream);
                    // 识别图片文字
                    String doOCR = tess4jClient.doOCR(bufferedImage);
                    // 审核是否包含自定义敏感词
                    boolean tessCheck = textCheck(wmNews, doOCR);
                    if(!tessCheck){
                        flag=false;
                    }
                    // ---------------图片文字识别信息结束-------------
                    //下面是调用阿里本地二进制图片审核,添加二进制数据到集合中
                    imageByteList.add(bytes);
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

        try {
            Map imgMap = greenImageScan.imageScan(imageByteList);
            if(imgMap.get("suggestion").equals("block")){
                //修改wm_news表的状态
                updateNewsStatus(wmNews, (short) 2,"非法图片信息");
                flag=false;
            }
            if(imgMap.get("suggestion").equals("review")){
                //修改wm_news表的状态
                updateNewsStatus(wmNews, (short) 3,"图片信息需要人工审核");
                flag=false;
            }
        } catch (Exception e) {
            e.printStackTrace();
            flag = false;
        }
        return flag;
    }

    /**
     * 文本信息审核
     * @param wmNews
     * @param content
     * @return
     */
    public boolean textCheck(WmNews wmNews, String content){
        boolean flag = true;
        if(content != null){
            try {
                Map textScan = greenTextScan.greeTextScan(content);
                if(textScan.get("suggestion").equals("block")){
                    // 有敏感词,修改文章状态
                    updateNewsStatus(wmNews, (short) 2, "审核失败，文本中包含敏感词");
                    flag = false;
                }
                //表示需要人工审核
                if(textScan.get("suggestion").equals("review")){
                    //修改wm_news表的状态
                    updateNewsStatus(wmNews, (short) 3,"文本中包含不确定词汇，需要人工审核");
                    flag=false;
                }
            } catch (Exception e) {
                e.printStackTrace();
                flag = false;
            }
        }
        return flag;
    }

    public void updateNewsStatus(WmNews wmNews, Short status, String msg){
        wmNews.setStatus(status);
        wmNews.setReason(msg);
        wmNewsMapper.updateById(wmNews);
    }

    /**
     * 抽取图片和文本信息
     * @param wmNews
     * @return hashMap
     */
    private Map<String, Object> drowOut(WmNews wmNews){
        // 存放图片信息
        List<String> imgList = new ArrayList<>();
        // 拼接标题和文本内容
        StringBuilder textBuffer = new StringBuilder();
        textBuffer.append(wmNews.getTitle());

        String content = wmNews.getContent(); // 获取文章内容信息
        List<Map> mapList = JSON.parseArray(content, Map.class);
        for (Map map : mapList) {
            if(map.get("type").equals("image")){
                imgList.add(map.get("value").toString());
            }
            if(map.get("type").equals("text")){
                String value = (String) map.get("value");
                textBuffer.append(value);
            }
        }
        //解析封面图片
        String images = wmNews.getImages();
        String[] split = images.split(",");
        imgList.addAll(Arrays.asList(split));
        Map<String, Object> hashMap = new HashMap<>();
        hashMap.put("content", textBuffer.toString());
        hashMap.put("imglist",imgList);
        return hashMap;
    }
}
